/* 桥接模式 */

/// 文件格式转换器
pub trait Transformer {

    /// 将数据格式转换并输出
    fn transform(&self);
}

/// 数据来源
pub trait DataSource {
    /// 读取数据
    fn read(&self);
}

mod sources {
    use super::*;

    pub struct FileSource {
        pub filename: String
    }
    
    impl DataSource for FileSource {
        fn read(&self) {
            println!("读取文件 {} 的内容", self.filename);
        }
    }

    pub struct DatabaseSource {
        pub host: String,
        pub port: u16
    }

    impl DataSource for DatabaseSource {
        fn read(&self) {
            println!("从数据库 {}:{} 读取数据", self.host, self.port);
        }
    }
}

mod transformers {
    use super::*;

    pub struct TxtTransformer {
        filename: String,
        source: Box<dyn DataSource>
    }

    impl TxtTransformer {
        pub fn new(filename: String, source: Box<dyn DataSource>) -> Self {
            Self {
                filename: filename,
                source: source
            }
        }
    }

    impl Transformer for TxtTransformer {

        /// 将数据格式转换并输出
        fn transform(&self) {
            self.source.read();
            println!("将数据输出为文本文件 {}", self.filename)
        }
    }

    pub struct ExcelTransformer {
        pub filename: String,
        pub source: Box<dyn DataSource>
    }

    impl Transformer for ExcelTransformer {

        /// 将数据格式转换并输出
        fn transform(&self) {
            self.source.read();
            println!("将数据输出为文本文件 {}", self.filename)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_bridge_1() {
        let datasource = sources::FileSource {
            filename: String::from("采购清单.xlst")
        };
        let transform = transformers::TxtTransformer::new(
            String::from("outout.txt"),
            Box::new(datasource));

        transform.transform();
    }

    #[test]
    fn test_bridge_2() {
        let datasource = sources::DatabaseSource {
            host: String::from("localhost"),
            port: 3306
        };

        let transform = transformers::ExcelTransformer {
            filename: String::from("output.xlst"),
            source: Box::new(datasource)
        };
        transform.transform();
    }
}